/**
 * @class Ext.ux.DataTip
 * @extends Ext.ToolTip. This plugin implements automatic tooltip generation for
 *          an arbitrary number of child nodes *within* a Component.
 * 
 * This plugin is applied to a high level Component, which contains repeating
 * elements, and depending on the host Component type, it automatically selects
 * a {@link Ext.ToolTip#delegate delegate} so that it appears when the mouse
 * enters a sub-element.
 * 
 * When applied to a GridPanel, this ToolTip appears when over a row, and the
 * Record's data is applied using this object's {@link #tpl} template.
 * 
 * When applied to a DataView, this ToolTip appears when over a view node, and
 * the Record's data is applied using this object's {@link #tpl} template.
 * 
 * When applied to a TreePanel, this ToolTip appears when over a tree node, and
 * the Node's {@link Ext.data.Model} record data is applied using this object's
 * {@link #tpl} template.
 * 
 * When applied to a FormPanel, this ToolTip appears when over a Field, and the
 * Field's `tooltip` property is used is applied using this object's
 * {@link #tpl} template, or if it is a string, used as HTML content. If there
 * is no `tooltip` property, the field itself is used as the template's data
 * object.
 * 
 * If more complex logic is needed to determine content, then the
 * {@link #beforeshow} event may be used. This class also publishes a
 * **`beforeshowtip`** event through its host Component. The *host Component*
 * fires the **`beforeshowtip`** event.
 */
Ext.define('Ext.ux.DataTip', function(DataTip) {

	// Target the body (if the host is a Panel), or, if there is no body, the
	// main Element.
	function onHostRender() {
		var e = this.isXType('panel') ? this.body : this.el;
		if (this.dataTip.renderToTarget) {
			this.dataTip.render(e);
		}
		this.dataTip.setTarget(e);
	}

	function updateTip(tip, data) {
		if (tip.rendered) {
			if (tip.host.fireEvent('beforeshowtip', tip.eventHost, tip, data) === false) {
				return false;
			}
			tip.update(data);
		} else {
			if (Ext.isString(data)) {
				tip.html = data;
			} else {
				tip.data = data;
			}
		}
	}

	function beforeViewTipShow(tip) {
		var rec = this.view.getRecord(tip.triggerElement), data;

		if (rec) {
			data = tip.initialConfig.data ? Ext.apply(tip.initialConfig.data,
					rec.data) : rec.data;
			return updateTip(tip, data);
		} else {
			return false;
		}
	}

	function beforeFormTipShow(tip) {
		var field = Ext.getCmp(tip.triggerElement.id);
		if (field && (field.tooltip || tip.tpl)) {
			return updateTip(tip, field.tooltip || field);
		} else {
			return false;
		}
	}

	return {
		extend : 'Ext.tip.ToolTip',

		mixins : {
			plugin : 'Ext.AbstractPlugin'
		},

		alias : 'plugin.datatip',

		lockableScope : 'both',

		constructor : function(config) {
			var me = this;
			me.callParent([config]);
			me.mixins.plugin.constructor.call(me, config);
		},

		init : function(host) {
			var me = this;

			me.mixins.plugin.init.call(me, host);
			host.dataTip = me;
			me.host = host;

			if (host.isXType('tablepanel')) {
				me.view = host.getView();
				if (host.ownerLockable) {
					me.host = host.ownerLockable;
				}
				me.delegate = me.delegate || me.view.getDataRowSelector();
				me.on('beforeshow', beforeViewTipShow);
			} else if (host.isXType('dataview')) {
				me.view = me.host;
				me.delegate = me.delegate || host.itemSelector;
				me.on('beforeshow', beforeViewTipShow);
			} else if (host.isXType('form')) {
				me.delegate = '.' + Ext.form.Labelable.prototype.formItemCls;
				me.on('beforeshow', beforeFormTipShow);
			} else if (host.isXType('combobox')) {
				me.view = host.getPicker();
				me.delegate = me.delegate || me.view.getItemSelector();
				me.on('beforeshow', beforeViewTipShow);
			}
			if (host.rendered) {
				onHostRender.call(host);
			} else {
				host.onRender = Ext.Function.createSequence(host.onRender,
						onHostRender);
			}
		}
	};
});